#include "defs.h"
#include "keyboard.h"


extern int numlock, caps, scrolllock;

/* creo el buffer del teclado inicializandolo para que aparezca vacio */

bufferT buff={{0},0,0};

/* Mapeo del teclado sacado de
 * http://ipoint.vlsi.uiuc.edu/web291/books/CH20/CH20-1.html */
static unsigned char keyboard [][CANT_KEYS] = 
{ 
		{NPC, ESC, '1', '2', '3', '4', '5', '6',
		'7', '8', '9', '0', '-', '=', '\b',	'\t', 
		'q', 'w', 'e', 'r',	't', 'y', 'u', 'i',
		'o', 'p', '[', ']',	'\n', NPC, 'a', 's',
		'd', 'f', 'g', 'h',	'j', 'k', 'l', ';',
		'\'', '`', NPC,	'\\', 'z', 'x',	'c', 'v',
		'b', 'n', 'm', ',', '.', '/', NPC, '*',
		NPC, ' ', NPC, NPC, NPC, NPC, NPC, NPC,
		NPC, NPC, NPC, NPC, NPC, NPC, NPC, NPC,
		UPKEY, NPC, NPC, NPC, NPC, NPC, NPC, NPC,
		DOWNKEY, NPC, NPC, NPC
		}, /* Shifteados */
		
		{NPC, NPC, '!', '@', '#', '$', '%', '^',
		'&', '*', '(', ')',	'_', '+', '\b', '\t',
		'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
		'O', 'P', '{', '}', '\n', NPC, 'A', 'S',
		'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
		'"', '~', NPC, '|', 'Z', 'X', 'C', 'V',
		'B', 'N', 'M', '<', '>', '?', NPC, NPC,
		NPC, ' ', NPC, NPC, NPC, NPC, NPC, NPC,
		NPC, NPC, NPC, NPC, NPC, NPC, NPC, NPC,
		UPKEY, NPC, NPC, NPC, NPC, NPC, NPC, NPC,
		DOWNKEY, NPC, NPC, NPC
		}
};  

unsigned char ctoa (int scancode, int shift, int caps)
{
	scancode &= 0x007F;			/* apago el ultimo bit para que no moleste */
	unsigned char c;
	int cant = sizeof(keyboard)/sizeof(keyboard[0][0]);

	c = keyboard[shift][scancode]; /* convierto el scancode a ascii */

	if(caps && !shift && IsLetter(c))
		c = toUpper(c);
	if(caps && shift && IsLetter(c))
		c = toLower(c);
		
	return c;
}

int
IsLetter(unsigned char c)		/* es letra? */
{
	if((c <= 'z' && c >= 'a') || (c <= 'Z' && c >= 'A'))
		return 1;
	return 0;
}

int
IsNumber(unsigned char c)		/* es numero? */
{
	if(c <= '9' && c >= '0')
		return 1;
	return 0;
}

unsigned char
toUpper(unsigned char c)		/* convierto a mayuscula */
{
	return (IsLower(c) ? (c - 'a' + 'A') : c);
}

int
IsLower(unsigned char c)		/* es minuscula minuscula? */
{
	if(c >= 'a' || c <= 'z')
		return 1;
	return 0;
}

unsigned char
toLower(unsigned char c)		/* convierto a minuscula */
{
	return (IsUpper(c) ? (c - 'A' + 'a') : c);
}

int
IsUpper(unsigned char c)		/* es minuscula mayuscula? */
{
	if(c >= 'A' || c <= 'Z')
		return 1;
	return 0;
}

int
BufferIsEmpty(bufferT * buff)	/* esta vacio el buffer? */
{
	return (buff->first==buff->last ? 1 : 0);
}

int
AddToBuffer(unsigned char c, bufferT * buff)
{							/* Pongo un caracter en el buffer del teclado */
	if((buff->last + 1) % MAX_BUFF == buff->first)
		return BUFF_FULL;

	buff->buffer[buff->last] = c;
	buff->last = (buff->last + 1) % MAX_BUFF;
}

int
GetFromBuffer(bufferT * buff)
{							/* Traigo un caracter del buffer del teclado */
	unsigned char c;
	
	if(!BufferIsEmpty(buff))
	{
		c = buff->buffer[buff->first];
		buff->first = (buff->first + 1) % MAX_BUFF;
	}
	else
		c = EOF;
	
	return c;
}

int
CheckBuffer(bufferT * buff)
{
	if(!BufferIsEmpty(buff))
		return buff->buffer[buff->first];
	return EOF;
}

int
GetChar(bufferT * buff)
{								/* Traigo un caracter */
	if(!BufferIsEmpty(buff))
		return GetFromBuffer(buff);
	return EOF;
}

void
setLights(void)
{
	char keys= 0;

	if( scrolllock )			/* seteo el char de luces de teclado */
		keys |= 1;
	if( numlock )
		keys |= 2;
	if( caps )
		keys |= 4;

	_Lights(keys);
	return;
}
